// 1.接口不能有具体的实现，可以用于描述 函数，对象，类，混合类型
// type IFullname = {
//     firstname:string,
//     lastname:string,
// }
// interface IFullname {
//     firstname:string
//     lastname:string
// }
// interface IFn {
//     (obj:IFullname): string
// }
// type IFn = {
//     (obj:IFullname): string
// }
// type 和 interface的区别
// 1.如果只是描述结构我们采用interface
// 2.如果涉及到联合类型，则只能使用type来进行声明
// 3.type不能被扩展，interface是可以扩展
// 4.type不能重名，interface重名可以合并
// 5.type在后续的学习中可以循环和条件 interface不行
// 6.其他情况下可以呼唤 (函数类型一般采用type来声明)
// const fullname:IFn = ({
//   firstname,
//   lastname
// }:IFullname) => {
//     return firstname + lastname;
// };
interface IFn {
    (): number; // 函数
    count: number // 属性
}
const click:IFn = () => {
    return click.count++ // 自定义属性
}
// 为了防止这个click函数被重新赋值 let是可以修改的，使用const就不一致了
click.count = 0;
// 一般情况下使用接口大概率都是描述对象
interface Iveg { //接口中声明的都是抽象的，而且必须要实现
    readonly color: string, // 仅读属性不能被随意修改
    size: number,
    taste: 'sweet' | 'sour', // 可选属性
    [xxxx: string]: any // 任意属性，key类型为string时，可以赋予number, string, symbol
}
interface IV extends Iveg {
    a?: number
}
// 5. let obj = {
    // color: "red",
    // size: 20,
    // taste: "sour",
    // a: 1
// }
// 
const tomato: Iveg = {
    color: "red",
    size: 20,
    taste: "sour",
    a: 1,
    1: 199,
    [Symbol()]: 'abc'
};
// tomato.color="green";
// 1.如果对象中的属性 多于接口可以直接采用断言的方式来赋值
// 2.可以基于接口特性写一个同名接口
// 3.产生新类型,通过继承原有属性的方式
// 4.通过任意类型来扩展(常用的用于一部分格式固定，一部分不固定)
// 5.类型兼容
// 6.交叉类型&。。。
interface Person {
    name: string;
    [key: string]: any
}
let p:Person = {
    name: "jiangjiang",
    age: 30
}
interface IArr {
   [key: number] :any 
}
let arr1:IArr = {
    0: '1',
    1: Symbol(),
    2: 3
};
let arr2: IArr = [1, 2, 3];
// 通过索引访问符，可以取值的类型

type PersonNameType = Person["name"];
type PersonAnyType = Person[string];

// keyof 取一个对象中key的集合 valueOf(自己实现) 取值的类型集合

interface ICar {
    color: string,
    a: 1,
    b: 2
}
type valueOf = ICar[keyof ICar]; // 通过索引操作符获取值的集合

// 接口 readonly ? 任意类型 [k:string]:any 接口[属性key]

interface ChineseSpeakable {
    a: 1,
    speakChinese(): void;
}
interface EnglishSpeakable {
    speakEnglish(): void;
}
class Speak implements ChineseSpeakable, EnglishSpeakable {
    public a:1 = 1;
    speakChinese(): void {
        console.log('说中国话');
    }
    speakEnglish(): void {

    }
}
export {}

